/**
 * @class $$.sql.writer.Writer
 */
$$.sql.writer.Writer = (function(){
	var 
	 sqlTpl_Insert = 'INSERT INTO {0} ({1}) VALUES ({2})'
	,sqlTpl_Update = 'UPDATE {0} SET {1} WHERE id = {2}'
	,sqlTpl_Delete = 'DELETE FROM {0} WHERE id = {1}';
	
	/**
	 * @param {Object} entityObj
	 * @param {Action} action
	 * @return {String} SQL语句。
	 */
	function write(entityObj, action){
		var sql;
		
		switch(action){
			case $$.data.INITIALIZE: // 新建表格。
				var insertData = entityObj.eachFields(entity2insert, [ [], [] ]);
				
		        sql = sqlTpl_Insert.format(
			         entityObj.getTableName()
			        ,insertData[0].join(',')
			        ,json2sql(insertData[1].join(','))
		        ); 
			break;
			case $$.data.CREATE: 	// 执行SQL INSERT指令。
				var insertData = entityObj.eachFields(entity2insert, [ [], [] ]);
				
		        sql = sqlTpl_Insert.format(
			         entityObj.getTableName()
			        ,insertData[0].join(',')
			        ,json2sql(insertData[1].join(','))
		        ); 
			break;
			case $$.data.UPDATE: 	// 执行SQL UPDATE指令。
		        var
		         updateData = entityObj.eachFields(entity2update, [])
		        ,updateData = updateData.join(',');
	
		        sql = sqlTpl_Update.format(entityObj.getTableName(), updateData, entityObj.id); 
			break;
			case $$.data.DELETE: 	// 输入记录的id参数，删除记录。
				sql = sqlTpl_Delete.format(entityObj.getTableName(), entityObj.id);
			break;
			default:
				// warn
			break;
		}
		
		return sql;
	}
	
	/**
	 * @this {Array}
	 */
	function entity2insert(field){
		this[0].push(field.key);
		this[1].push(field.getSqlValue());
	}
	
	/**
	 * @this {Array}
	 */
	function entity2update(field){
		this.push(field.key + ' = ' + field.getSqlValue()); 
	}

	/**
	 * 送入一个JSON值，根据其类型返回符合SQL存储的字符串。
	 * @private
	 * @param 	{Any}	 v 	值
	 * @return 	{String} 	符合sQL存储的字符串。
	 */
	function json2sql(v){
	    switch(typeof(v)){
	        case 'boolean':
	        	break;
	        case 'string':
	            v = v.replace(/\'/g, "''").replace(/\r/g,"").replace(/(wh)(ere)/ig, "$1'+'$2");
			    v = "'"+ v +"'";
			break;
			case 'number':
				/*
				 * Access 双精度数字需要转换
				 * @dep
				if(false){
					v = " Format(" + v + ",'#0.0000') ";
				}*/
			break;
			case 'object':
	            if(v.toString() === new Date(v).toString()){ // 日期类型
	               v = (
	                $$.cfg.edk_dbType == 'mysql'
	                ? "'" + $$.Date.dateFormat(v, "yyyy-mm-dd HH:MM:ss") + "'"
	                : "#" + $$.Date.dateFormat(v, "yyyy-mm-dd HH:MM:ss") + "#"
	               );
	               break; 
	            }
			default : 
	            throw "unknow type!";
	    }
	    return v;
	}

	/**
	 * 这里一定要转换，因为COM日期类型到JS中很奇怪。
	 * 原理ADO Types -->JS Types
	 * 以字符出现date字眼为判断！
	 * @param {String} key
	 * @param {COM/COM+} v
	 * @return {Date}
	 */
	function getPrimitiveDate(key, v){
	    if(/date/i.test(key)){
	        v = new Date(v);
	    }
	    return v;
	}
	
	return {
		 add	: write.delegate(this, $$.data.CREATE)
		,update : write.delegate(this, $$.data.UPDATE)
		,delte	: write.delegate(this, $$.data.DELETE)
			
		/**
		 * 新建表格。
		 * @param 	{Object} 	entityObj
		 * @param 	{Boolean} 	isDropTable 	创建表格之前是否删除表格。
		 * @return 	{Boolean} 					True表示创建成功。
		 */
		,createTable : function(entityObj, isDropTable){
			var  
			 sql  = 'CREATE TABLE ' + tableName
			,meta = $$.Model.meta
			,fieldName
			,SQLType
			,arr  = [];
				
			for(fieldName in model){
				SQLType =  meta.getMeta.call(model[fieldName], meta.SQLType);
				switch(SQLType){
					case 'BOOLEAN':
						SQLType = ($$.cfg.edk_dbType == 'access') ? 'BIT' : SQLType;
					break;
					case 'CHAR':
						SQLType = 'CHAR({0})'.format(meta.getMeta.call(model[fieldName], meta.Length))
					break;
				}
				arr.push(fieldName + ' ' + SQLType + (fieldName == "ID" ? " NOT NULL PRIMARY KEY" : ""));
			}
			sql += '('+ arr.join('\n,') + ")";
			
			if(isDropTable){
				 	// Access不支持 IF EXIST……
					$$.sql.execute('DROP TABLE {0}'.format(tableName));
			}
			//进行数据库操作
			return sql;
		}
	};
})();